package uba.ing2.subite.demo;

import java.text.DecimalFormat;
import java.util.Collection;

import org.apache.pivot.collections.ArrayList;
import org.apache.pivot.collections.List;
import org.apache.pivot.collections.Sequence;
import org.apache.pivot.collections.adapter.ListAdapter;
import org.apache.pivot.util.concurrent.Task;
import org.apache.pivot.util.concurrent.TaskListener;
import org.apache.pivot.wtk.Button;
import org.apache.pivot.wtk.ButtonPressListener;
import org.apache.pivot.wtk.CardPane;
import org.apache.pivot.wtk.Component;
import org.apache.pivot.wtk.Container;
import org.apache.pivot.wtk.Label;
import org.apache.pivot.wtk.ListView;
import org.apache.pivot.wtk.ListViewSelectionListener;
import org.apache.pivot.wtk.PushButton;
import org.apache.pivot.wtk.Span;
import org.apache.pivot.wtk.TableView;
import org.apache.pivot.wtk.TaskAdapter;
import org.apache.pivot.wtk.Window;
import org.apache.pivot.wtkx.Bindable;
import org.apache.pivot.wtkx.WTKX;

import uba.ing2.subite.domain.DisposableCard;
import uba.ing2.subite.domain.PaidInvoice;
import uba.ing2.subite.domain.PaymentCard;
import uba.ing2.subite.domain.PaymentCardVisitor;
import uba.ing2.subite.domain.PrepaidCard;
import uba.ing2.subite.services.PaymentRegistrationService;
import uba.ing2.subite.services.PaymentRejectedException;
import uba.ing2.subite.services.PaymentService;

public class SubiteDemoWindow extends Window implements Bindable {
	@WTKX(id="autobusTerminal.terminalScreenPane") private CardPane terminalScreenPane = null;
	@WTKX(id="autobusTerminal.ticketValueLabel") private Label ticketValueLabel = null;
	@WTKX(id="autobusTerminal.usePaymentCardButton") private PushButton usePaymentCardButton = null;
	@WTKX(id="autobusTerminal.cancelButton") private PushButton cancelButton = null;	
	@WTKX(id="autobusTerminal.ticketValueSelectionPane") private Container ticketValueSelectionPane = null;
	@WTKX(id="autobusTerminal.cardSelectionList") private ListView cardSelectionList = null;
	@WTKX(id="autobusTerminal.cardView") private CardPane cardView = null;
	@WTKX(id="autobusTerminal.disposableCardIdentifierLabel") private Label disposableCardIdentifierLabel = null;
	@WTKX(id="autobusTerminal.disposableCardAvailableMoneyLabel") private Label disposableCardAvailableMoneyLabel = null;
	@WTKX(id="autobusTerminal.prepaidCardIdentifierLabel") private Label prepaidCardIdentifierLabel = null;
	@WTKX(id="autobusTerminal.prepaidCardAvailableMoneyLabel") private Label prepaidCardAvailableMoneyLabel = null;
	@WTKX(id="autobusTerminal.accountIdentifierLabel") private Label accountIdentifierLabel = null;
	@WTKX(id="autobusTerminal.errorMessageLabel") private Label errorMessageLabel = null;
	@WTKX(id="server.trackPaidInvoiceList") private TableView trackPaidInvoiceList = null;
	
	private SubiteDemoModel model;
	private DecimalFormat moneyFormat = new DecimalFormat("$ ##.00");

    private ButtonPressListener selectTicketAction = new ButtonPressListener() {
		@SuppressWarnings("unchecked")
		@Override
		public void buttonPressed(Button button) {
			StringView<Number> buttonData = (StringView<Number>) button.getButtonData();
			model.setSelectedTicketValue(buttonData.getValue());
			ticketValueLabel.setText("Utilice la tarjeta para pagar " + button.getButtonData());
			terminalScreenPane.setSelectedIndex(1);
			usePaymentCardButton.setEnabled(true);
			
		}
    };
	private PaymentService paymentService;
	private PaymentRegistrationService paymentRegistrationService;

	@Override
	public void initialize() {
		usePaymentCardButton.getButtonPressListeners().add(new ButtonPressListener() {
			@Override
			public void buttonPressed(Button button) {
				try {
					paymentService.processPayment(model.getBusTripInvoice(), model.getSelectedCard());
				} catch (PaymentRejectedException e) {
					showError(e.getMessage());
				}
				terminalScreenPane.setSelectedIndex(0);
				usePaymentCardButton.setEnabled(false);
				showCard(model.getSelectedCard());
				refreshPaidInvoiceList();
			}
		});
		cancelButton.getButtonPressListeners().add(new ButtonPressListener() {
			@Override
			public void buttonPressed(Button arg0) {
				terminalScreenPane.setSelectedIndex(0);
				usePaymentCardButton.setEnabled(false);
			}
		});

		cardSelectionList.getListViewSelectionListeners().add(new ListViewSelectionListener.Adapter() {
			@SuppressWarnings("unchecked")
			@Override
			public void selectedRangesChanged(ListView listView, Sequence<Span> previousSelected) {
				PaymentCard paymentCard = ((StringView<PaymentCard>) listView.getSelectedItem()).getValue();
				model.setSelectedCard(paymentCard);
				showCard(paymentCard);
			}
		});
	}
	
	private void showError(String message) {
		errorMessageLabel.setText("Error: " + message);
		terminalScreenPane.setStyles("{selectionChangeEffect:'CROSSFADE'}");
		terminalScreenPane.setSelectedIndex(2);
        SleepTask sleepTask = new SleepTask(2000);

        TaskListener<Void> taskListener = new TaskListener<Void>() {
            @Override
            public void taskExecuted(Task<Void> task) {
            	hideError();
            }

            @Override
            public void executeFailed(Task<Void> task) {}
        };

        sleepTask.execute(new TaskAdapter<Void>(taskListener));
		
	}

	protected void hideError() {
		terminalScreenPane.setStyles("{selectionChangeEffect:'CROSSFADE'}");
		terminalScreenPane.setSelectedIndex(0);
		terminalScreenPane.setStyles("{selectionChangeEffect:'ZOOM'}");
	}

	private void showCard(PaymentCard paymentCard) {
		paymentCard.accept(new PaymentCardVisitor() {
			@Override
			public void visitDisposableCard(DisposableCard disposableCard) {
				disposableCardIdentifierLabel.setText(disposableCard.identifier().toString());
				disposableCardAvailableMoneyLabel.setText(formatMoney(disposableCard.moneyAvailable()));
				cardView.setSelectedIndex(0);
			}

			@Override
			public void visitPrepaidCard(PrepaidCard prepaidCard) {
				prepaidCardIdentifierLabel.setText(prepaidCard.identifier().toString());
				prepaidCardAvailableMoneyLabel.setText(formatMoney(prepaidCard.moneyAvailable()));
				accountIdentifierLabel.setText(prepaidCard.accountIdentifier().toString());
				cardView.setSelectedIndex(1);
			}
		});
	}

	private String formatMoney(Number value) {
		return moneyFormat.format(value);
	}

	private Component createTicketValueButtonWith(Number value) {
		PushButton button = new PushButton(StringView.create(value, formatMoney(value)));
		button.getButtonPressListeners().add(selectTicketAction);
		button.setStyles("{padding:20}");
		return button;
	}

	public void initializeWith(SubiteDemoModel model, PaymentService paymentService, PaymentRegistrationService paymentRegistrationService) {
		this.model = model;
		this.paymentService = paymentService;
		this.paymentRegistrationService = paymentRegistrationService;
		for (Number value : model.getTicketValues()) {
			ticketValueSelectionPane.add(createTicketValueButtonWith(value));	
		}
		cardSelectionList.setListData(new ListAdapter<StringView<PaymentCard>>(model.getPaymentCardsWithDescription()));
		cardSelectionList.setSelectedIndex(0);
		refreshPaidInvoiceList();
	}

	private void refreshPaidInvoiceList() {
		trackPaidInvoiceList.setTableData(adaptPaidInvoiceData(paymentRegistrationService.allPayments()));
	}

	private List<PaidInvoiceView> adaptPaidInvoiceData(Collection<PaidInvoice> allPayments) {
		List<PaidInvoiceView> result = new ArrayList<PaidInvoiceView>();
		for (PaidInvoice paidInvoice : allPayments) {
			result.add(new PaidInvoiceView(paidInvoice));
		}
		return result;
	}
}
